package com.fr.base.core.antlr;

import com.fr.base.core.antlr.ASdebug.ASDebugStream;
import com.fr.base.core.antlr.ASdebug.IASDebugStream;
import com.fr.base.core.antlr.ASdebug.TokenOffsetInfo;
import com.fr.base.core.antlr.collections.impl.BitSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TokenStreamRewriteEngine
  implements TokenStream, IASDebugStream
{
  public static final int MIN_TOKEN_INDEX = 0;
  public static final String DEFAULT_PROGRAM_NAME = "default";
  public static final int PROGRAM_INIT_SIZE = 100;
  protected List tokens;
  protected Map programs;
  protected Map lastRewriteTokenIndexes;
  protected int index;
  protected TokenStream stream;
  protected BitSet discardMask;

  public TokenStreamRewriteEngine(TokenStream paramTokenStream)
  {
    this(paramTokenStream, 1000);
  }

  public TokenStreamRewriteEngine(TokenStream paramTokenStream, int paramInt)
  {
    this.programs = null;
    this.lastRewriteTokenIndexes = null;
    this.index = 0;
    this.discardMask = new BitSet();
    this.stream = paramTokenStream;
    this.tokens = new ArrayList(paramInt);
    this.programs = new HashMap();
    this.programs.put("default", new ArrayList(100));
    this.lastRewriteTokenIndexes = new HashMap();
  }

  public Token nextToken()
    throws TokenStreamException
  {
    TokenWithIndex localTokenWithIndex;
    do
    {
      localTokenWithIndex = (TokenWithIndex)this.stream.nextToken();
      if (localTokenWithIndex != null)
      {
        localTokenWithIndex.setIndex(this.index);
        if (localTokenWithIndex.getType() != 1)
          this.tokens.add(localTokenWithIndex);
        this.index += 1;
      }
    }
    while ((localTokenWithIndex != null) && (this.discardMask.member(localTokenWithIndex.getType())));
    return localTokenWithIndex;
  }

  public void rollback(int paramInt)
  {
    rollback("default", paramInt);
  }

  public void rollback(String paramString, int paramInt)
  {
    List localList = (List)this.programs.get(paramString);
    if (localList != null)
      this.programs.put(paramString, localList.subList(0, paramInt));
  }

  public void deleteProgram()
  {
    deleteProgram("default");
  }

  public void deleteProgram(String paramString)
  {
    rollback(paramString, 0);
  }

  protected void addToSortedRewriteList(RewriteOperation paramRewriteOperation)
  {
    addToSortedRewriteList("default", paramRewriteOperation);
  }

  protected void addToSortedRewriteList(String paramString, RewriteOperation paramRewriteOperation)
  {
    List localList = getProgram(paramString);
    1 local1 = new Comparator(this)
    {
      private final TokenStreamRewriteEngine this$0;

      public int compare(, Object paramObject2)
      {
        TokenStreamRewriteEngine.RewriteOperation localRewriteOperation1 = (TokenStreamRewriteEngine.RewriteOperation)paramObject1;
        TokenStreamRewriteEngine.RewriteOperation localRewriteOperation2 = (TokenStreamRewriteEngine.RewriteOperation)paramObject2;
        if (localRewriteOperation1.index < localRewriteOperation2.index)
          return -1;
        if (localRewriteOperation1.index > localRewriteOperation2.index)
          return 1;
        return 0;
      }
    };
    int i = Collections.binarySearch(localList, paramRewriteOperation, local1);
    if (i >= 0)
    {
      while (i >= 0)
      {
        RewriteOperation localRewriteOperation1 = (RewriteOperation)localList.get(i);
        if (localRewriteOperation1.index < paramRewriteOperation.index)
          break;
        --i;
      }
      ++i;
      if (paramRewriteOperation instanceof ReplaceOp)
      {
        int j = 0;
        for (int k = i; k < localList.size(); ++k)
        {
          RewriteOperation localRewriteOperation2 = (RewriteOperation)localList.get(i);
          if (localRewriteOperation2.index != paramRewriteOperation.index)
            break;
          if (localRewriteOperation2 instanceof ReplaceOp)
          {
            localList.set(i, paramRewriteOperation);
            j = 1;
            break;
          }
        }
        if (j == 0)
          localList.add(k, paramRewriteOperation);
      }
      else
      {
        localList.add(i, paramRewriteOperation);
      }
    }
    else
    {
      localList.add(-i - 1, paramRewriteOperation);
    }
  }

  public void insertAfter(Token paramToken, String paramString)
  {
    insertAfter("default", paramToken, paramString);
  }

  public void insertAfter(int paramInt, String paramString)
  {
    insertAfter("default", paramInt, paramString);
  }

  public void insertAfter(String paramString1, Token paramToken, String paramString2)
  {
    insertAfter(paramString1, ((TokenWithIndex)paramToken).getIndex(), paramString2);
  }

  public void insertAfter(String paramString1, int paramInt, String paramString2)
  {
    insertBefore(paramString1, paramInt + 1, paramString2);
  }

  public void insertBefore(Token paramToken, String paramString)
  {
    insertBefore("default", paramToken, paramString);
  }

  public void insertBefore(int paramInt, String paramString)
  {
    insertBefore("default", paramInt, paramString);
  }

  public void insertBefore(String paramString1, Token paramToken, String paramString2)
  {
    insertBefore(paramString1, ((TokenWithIndex)paramToken).getIndex(), paramString2);
  }

  public void insertBefore(String paramString1, int paramInt, String paramString2)
  {
    addToSortedRewriteList(paramString1, new InsertBeforeOp(paramInt, paramString2));
  }

  public void replace(int paramInt, String paramString)
  {
    replace("default", paramInt, paramInt, paramString);
  }

  public void replace(int paramInt1, int paramInt2, String paramString)
  {
    replace("default", paramInt1, paramInt2, paramString);
  }

  public void replace(Token paramToken, String paramString)
  {
    replace("default", paramToken, paramToken, paramString);
  }

  public void replace(Token paramToken1, Token paramToken2, String paramString)
  {
    replace("default", paramToken1, paramToken2, paramString);
  }

  public void replace(String paramString1, int paramInt1, int paramInt2, String paramString2)
  {
    addToSortedRewriteList(new ReplaceOp(paramInt1, paramInt2, paramString2));
  }

  public void replace(String paramString1, Token paramToken1, Token paramToken2, String paramString2)
  {
    replace(paramString1, ((TokenWithIndex)paramToken1).getIndex(), ((TokenWithIndex)paramToken2).getIndex(), paramString2);
  }

  public void delete(int paramInt)
  {
    delete("default", paramInt, paramInt);
  }

  public void delete(int paramInt1, int paramInt2)
  {
    delete("default", paramInt1, paramInt2);
  }

  public void delete(Token paramToken)
  {
    delete("default", paramToken, paramToken);
  }

  public void delete(Token paramToken1, Token paramToken2)
  {
    delete("default", paramToken1, paramToken2);
  }

  public void delete(String paramString, int paramInt1, int paramInt2)
  {
    replace(paramString, paramInt1, paramInt2, null);
  }

  public void delete(String paramString, Token paramToken1, Token paramToken2)
  {
    replace(paramString, paramToken1, paramToken2, null);
  }

  public void discard(int paramInt)
  {
    this.discardMask.add(paramInt);
  }

  public TokenWithIndex getToken(int paramInt)
  {
    return ((TokenWithIndex)this.tokens.get(paramInt));
  }

  public int getTokenStreamSize()
  {
    return this.tokens.size();
  }

  public String toOriginalString()
  {
    return toOriginalString(0, getTokenStreamSize() - 1);
  }

  public String toOriginalString(int paramInt1, int paramInt2)
  {
    StringBuffer localStringBuffer = new StringBuffer();
    for (int i = paramInt1; (i >= 0) && (i <= paramInt2) && (i < this.tokens.size()); ++i)
      localStringBuffer.append(getToken(i).getText());
    return localStringBuffer.toString();
  }

  public String toString()
  {
    return toString(0, getTokenStreamSize() - 1);
  }

  public String toString(String paramString)
  {
    return toString(paramString, 0, getTokenStreamSize() - 1);
  }

  public String toString(int paramInt1, int paramInt2)
  {
    return toString("default", paramInt1, paramInt2);
  }

  public String toString(String paramString, int paramInt1, int paramInt2)
  {
    List localList = (List)this.programs.get(paramString);
    if ((localList == null) || (localList.size() == 0))
      return toOriginalString(paramInt1, paramInt2);
    StringBuffer localStringBuffer = new StringBuffer();
    RewriteOperation localRewriteOperation1 = 0;
    int i = paramInt1;
    while (true)
    {
      do
      {
        if ((i < 0) || (i > paramInt2) || (i >= this.tokens.size()))
          break label247;
        if (localRewriteOperation1 < localList.size())
        {
          localRewriteOperation2 = (RewriteOperation)localList.get(localRewriteOperation1);
          while (true)
          {
            do
              if ((localRewriteOperation2.index >= i) || (localRewriteOperation1 >= localList.size()))
                break label157;
            while (++localRewriteOperation1 >= localList.size());
            localRewriteOperation2 = (RewriteOperation)localList.get(localRewriteOperation1);
          }
          while (true)
          {
            do
            {
              label157: if ((i != localRewriteOperation2.index) || (localRewriteOperation1 >= localList.size()))
                break label220;
              i = localRewriteOperation2.execute(localStringBuffer);
            }
            while (++localRewriteOperation1 >= localList.size());
            label220: localRewriteOperation2 = (RewriteOperation)localList.get(localRewriteOperation1);
          }
        }
      }
      while (i > paramInt2);
      localStringBuffer.append(getToken(i).getText());
      ++i;
    }
    for (RewriteOperation localRewriteOperation2 = localRewriteOperation1; localRewriteOperation2 < localList.size(); ++localRewriteOperation2)
    {
      label247: RewriteOperation localRewriteOperation3 = (RewriteOperation)localList.get(localRewriteOperation2);
      if (localRewriteOperation3.index >= size())
        localRewriteOperation3.execute(localStringBuffer);
    }
    return localStringBuffer.toString();
  }

  public String toDebugString()
  {
    return toDebugString(0, getTokenStreamSize() - 1);
  }

  public String toDebugString(int paramInt1, int paramInt2)
  {
    StringBuffer localStringBuffer = new StringBuffer();
    for (int i = paramInt1; (i >= 0) && (i <= paramInt2) && (i < this.tokens.size()); ++i)
      localStringBuffer.append(getToken(i));
    return localStringBuffer.toString();
  }

  public int getLastRewriteTokenIndex()
  {
    return getLastRewriteTokenIndex("default");
  }

  protected int getLastRewriteTokenIndex(String paramString)
  {
    Integer localInteger = (Integer)this.lastRewriteTokenIndexes.get(paramString);
    if (localInteger == null)
      return -1;
    return localInteger.intValue();
  }

  protected void setLastRewriteTokenIndex(String paramString, int paramInt)
  {
    this.lastRewriteTokenIndexes.put(paramString, new Integer(paramInt));
  }

  protected List getProgram(String paramString)
  {
    List localList = (List)this.programs.get(paramString);
    if (localList == null)
      localList = initializeProgram(paramString);
    return localList;
  }

  private List initializeProgram(String paramString)
  {
    ArrayList localArrayList = new ArrayList(100);
    this.programs.put(paramString, localArrayList);
    return localArrayList;
  }

  public int size()
  {
    return this.tokens.size();
  }

  public int index()
  {
    return this.index;
  }

  public String getEntireText()
  {
    return ASDebugStream.getEntireText(this.stream);
  }

  public TokenOffsetInfo getOffsetInfo(Token paramToken)
  {
    return ASDebugStream.getOffsetInfo(this.stream, paramToken);
  }

  static class DeleteOp extends TokenStreamRewriteEngine.ReplaceOp
  {
    public DeleteOp(int paramInt1, int paramInt2)
    {
      super(paramInt1, paramInt2, null);
    }
  }

  static class ReplaceOp extends TokenStreamRewriteEngine.RewriteOperation
  {
    protected int lastIndex;

    public ReplaceOp(int paramInt1, int paramInt2, String paramString)
    {
      super(paramInt1, paramString);
      this.lastIndex = paramInt2;
    }

    public int execute(StringBuffer paramStringBuffer)
    {
      if (this.text != null)
        paramStringBuffer.append(this.text);
      return (this.lastIndex + 1);
    }
  }

  static class InsertBeforeOp extends TokenStreamRewriteEngine.RewriteOperation
  {
    public InsertBeforeOp(int paramInt, String paramString)
    {
      super(paramInt, paramString);
    }

    public int execute(StringBuffer paramStringBuffer)
    {
      paramStringBuffer.append(this.text);
      return this.index;
    }
  }

  static class RewriteOperation
  {
    protected int index;
    protected String text;

    protected RewriteOperation(int paramInt, String paramString)
    {
      this.index = paramInt;
      this.text = paramString;
    }

    public int execute(StringBuffer paramStringBuffer)
    {
      return this.index;
    }

    public String toString()
    {
      String str = super.getClass().getName();
      int i = str.indexOf(36);
      str = str.substring(i + 1, str.length());
      return str + "@" + this.index + '"' + this.text + '"';
    }
  }
}